/*
 * Copyright (C) 2011-2021 ShenZhen iBOXCHAIN Information Technology Co.,Ltd.
 *
 * All right reserved.
 *
 * This software is the confidential and proprietary
 * information of iBOXCHAIN Company of China.
 * ("Confidential Information"). You shall not disclose
 * such Confidential Information and shall use it only
 * in accordance with the terms of the contract agreement
 * you entered into with iBOXCHAIN inc.
 *
 */
package cn.anoxia.springframework.beans.support;

import cn.anoxia.springframework.beans.BeansException;
import cn.anoxia.springframework.beans.ObjectFactory;
import cn.anoxia.springframework.beans.factory.DisposableBean;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @author huangle
 */
public class DefaultSingletonBeanRegistry implements SingletonBeanRegistry{

  protected static final Object NULL_OBJECT = new Object();

  // 一级缓存 普通对象
  private Map<String,Object> singletonObjects = new HashMap<>();

  // 二级缓存 提前暴露对象，没有完全实例化的对象
  protected final Map<String, Object> earlySingletonObjects = new HashMap<String,
          Object>();

  // 三级缓存，存放代理对象
  private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>();

  private final Map<String, DisposableBean> disposableBeans = new LinkedHashMap<>();


  @Override
  public Object getSingleton(String name) throws BeansException {
    Object o = singletonObjects.get(name);
    if (null == o){
      // 判断二级缓存中是否有对象，这个对象就是代理对象，因为只有代理对象才会放到三
      // 级缓存中
      o = earlySingletonObjects.get(name);
      if (o == null){
        // 从三级缓存中获取
        ObjectFactory<?> singletonFactory = singletonFactories.get(name);
        if (singletonFactory != null){
          o = singletonFactory.getObject();
          earlySingletonObjects.put(name,o);
          singletonObjects.put(name,o);
        }
      }
    }
    return o;
  }

  @Override
  public void registerSingleton(String beanName, Object singletonObject) {
    singletonObjects.put(beanName, singletonObject);
    earlySingletonObjects.remove(beanName);
    singletonFactories.remove(beanName);
  }

  protected void addSingletonFactory(String beanName,ObjectFactory<?> singletonFactory){
    if (!this.singletonObjects.containsKey(beanName)){
      this.singletonFactories.put(beanName,singletonFactory);
      this.earlySingletonObjects.remove(beanName);
    }
  }

  protected void addSingleton(String beanName, Object singletonObject){
    singletonObjects.put(beanName, singletonObject);
  }

  public void registerDisposableBean(String beanName, DisposableBean bean) {
    disposableBeans.put(beanName, bean);
  }


}
